import flash.display.Sprite;
import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.SyncEvent;
import flash.net.NetConnection;
import flash.net.SharedObject;

class Main extends Sprite
{
	static var app:String="/minimal/so";
	var nc:NetConnection;
	var so:SharedObject;
	var ball:Sprite;
	public static function main()
	{
		flash.Lib.current.addChild(new Main());
	}
	public function new()
	{
		super();
		
		ball = createBall();
		addChild(ball);
		
		nc = new NetConnection();
		nc.client = this;
		nc.objectEncoding = 0;
		nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
		nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onConnectionError);
		
		addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
	}
	function onAddedToStage(event:Event)
	{
		removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		var uri = getUri();
		trace("connecting to rtmp://" + uri);
		nc.connect("rtmp://"+uri);
	}
	//monitor connection
	function onConnectionError(event:AsyncErrorEvent):Void
	{
		trace("nc onConnectionError currentTarget=" + event.currentTarget + ", error=" + event.error);
	}
	function onConnectionStatus(event:NetStatusEvent):Void
	{
		var msg = "nc onConnectionStatus code="+event.info.code;
		if(event.info.description!=null)
			msg += ", description=" + event.info.description;
		trace(msg);
		if(event.info.code == "NetConnection.Connect.Success")
		{
			so = SharedObject.getRemote("ballData", nc.uri, true);
			so.connect(nc);
			so.client = this; 
			so.addEventListener(NetStatusEvent.NET_STATUS, onSharedObjectStatus);
			so.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onSharedObjectError);
			so.addEventListener(SyncEvent.SYNC, onSharedObjectSync);

			stage.addEventListener(MouseEvent.CLICK, onStageClick);
		}
	}
	
	//monitor shared object
	function onSharedObjectError(event:AsyncErrorEvent):Void
	{
		trace("so onSharedObjectError currentTarget="+event.currentTarget+", error=" + event.error);
	}
	function onSharedObjectStatus(event:NetStatusEvent):Void
	{
		var msg = "so onSharedObjectStatus code="+event.info.code;
		if(event.info.description!=null)
			msg +=", description=" + event.info.description;
		trace(msg);
	}
	function onSharedObjectSync(event:SyncEvent)
	{
		var msg = "so onSharedObjectSync event=" + event;
		trace(msg);
		if(so.data.ballX!=null && so.data.ballY!=null)
		{
			ball.x = so.data.ballX;
			ball.y = so.data.ballY;
		}
	}
	function onStageClick(event:Event)
	{
		trace('so: sending: "testMessage", true, Date.now(), ["zero", "one", {two:2, three:3}');
		so.send("testMessage", true, Date.now(), ["zero", "one", {two:2, three:3}] );//calls the functino testMessage on every subscriber of this shared object
	}
	function testMessage( b:Bool, d:Date, a:Array<Dynamic>)
	{
		trace('received:');
		//trace(i);
		//trace(s);
		trace(b);
		trace(d);
		trace(a);
	}
	
	//ball handling
	function createBall()
	{
		ball = new Sprite();
		ball.buttonMode = true;
		ball.graphics.lineStyle(1, 0);
        ball.graphics.beginFill(0xff0000);
		ball.graphics.drawCircle(50, 50, 50);
		ball.graphics.endFill();
		ball.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
		return ball;
	}
	private function onStartDrag(event:MouseEvent)
	{
		ball.startDrag();
		stage.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);
		stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
	}
	private function onStopDrag(event:MouseEvent)
	{
		ball.stopDrag();
		stage.removeEventListener(MouseEvent.MOUSE_UP, onStopDrag);
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
	}
	private function onMouseMove(event:MouseEvent)
	{
		so.setProperty("ballX", ball.x);
		so.setProperty("ballY", ball.y);
	}
	function getUri():String
	{
		var parameters:Dynamic = flash.Lib.current.loaderInfo.parameters;
		//trace(parameters);
		var u = Reflect.field(parameters, "uri");
		if(u!=null)
			return u;
		var h = Reflect.field(parameters, "host");
		var p = Reflect.field(parameters, "port");
		var a = Reflect.field(parameters, "app");
		return (h==null?"localhost":h) + (p==null?":1935":":"+p) + (a==null?app:a);
	}
}
